<template>
  <div id="app" class="deepseek-container" v-cloak>
    <!-- 侧边栏 -->
    <div class="deepseek-sidebar">
      <div class="deepseek-new-chat" @click="createNewChat">
        <i class="bi bi-plus-lg"></i>&nbsp;新建聊天
      </div>
      <div class="deepseek-history">
        <!-- 历史记录功能可以在未来实现 -->
      </div>
    </div>
    <!-- 主聊天区域 -->
    <div class="deepseek-chat">
      <div class="deepseek-chat-header">
        AI 聊天助手
        <div class="voice-toggle">
          <span>语音播报</span>
          <label class="switch">
            <input type="checkbox" v-model="voiceEnabled">
            <span class="slider round"></span>
          </label>
        </div>
        <!-- 添加数字人开关 -->
        <div class="avatar-toggle">
          <span>数字人</span>
          <label class="switch">
            <input type="checkbox" v-model="avatarEnabled">
            <span class="slider round"></span>
          </label>
        </div>
      </div>
      <div id="chatBox" class="deepseek-messages">
        <!-- 欢迎消息 -->
        <div v-if="!messages || messages.length === 0" class="deepseek-welcome">
          <h2>欢迎使用 AI 聊天助手</h2>
          <p>请输入您的问题，我会尽力为您解答。</p>
        </div>
        <!-- 消息展示 -->
        <template v-else>
          <div v-for="message in messages" :key="message.id" 
              :class="['deepseek-message', message.isUser ? 'deepseek-message-user' : 'deepseek-message-ai']"
              :id="`message-${message.id}`">
            <template v-if="message.isUser">
              <div class="avatar">
                <svg width="28" height="28" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
                  <circle cx="24" cy="24" r="20" fill="#ffe4b5"/>
                  <ellipse cx="17" cy="22" rx="3" ry="4" fill="#333"/>
                  <ellipse cx="31" cy="22" rx="3" ry="4" fill="#333"/>
                  <ellipse cx="24" cy="32" rx="7" ry="4" fill="#fff"/>
                  <ellipse cx="24" cy="32" rx="4" ry="2" fill="#333"/>
                  <path d="M8 10 Q12 4 18 10" stroke="#333" stroke-width="2" stroke-linecap="round" fill="none"/>
                  <path d="M40 10 Q36 4 30 10" stroke="#333" stroke-width="2" stroke-linecap="round" fill="none"/>
                </svg>
              </div>
              <div class="message-content">
                {{ message.content }}
              </div>
              <small class="timestamp">{{ new Date(message.timestamp).toLocaleString() }}</small>
            </template>
            <template v-else-if="message.thinking">
              <div class="avatar">
                <i class="bi bi-robot"></i>
              </div>
              <div v-html="message.content"></div>
              <small class="timestamp">{{ new Date(message.timestamp).toLocaleString() }}</small>
            </template>
            <template v-else>
              <div class="avatar">
                <i class="bi bi-robot"></i>
              </div>
              <div class="message-content-wrapper" style="flex:1;display:flex;flex-direction:column;">
                <div class="message-content">
                  <div v-html="message.content"></div>
                  <span v-if="message.typing" class="typing-cursor"></span>
                </div>
                <div class="message-actions">
                  <i class="bi bi-hand-thumbs-up" @click="likeMessage(message)" :class="{ 'liked': message.liked }" title="点赞"></i>
                  <i class="bi bi-hand-thumbs-down" @click="dislikeMessage(message)" :class="{ 'disliked': message.disliked }" title="不喜欢"></i>
                  <i class="bi bi-clipboard" @click="copyMessage(message)" title="复制"></i>
                  <i class="bi bi-arrow-clockwise" @click="retryMessage(message)" title="重试"></i>
                  <i v-if="message.content.length > 500" class="bi bi-arrows-angle-expand" @click="expandMessage(message)" title="查看全文"></i>
                </div>
                <small class="timestamp">{{ new Date(message.timestamp).toLocaleString() }}</small>
              </div>
            </template>
          </div>
        </template>
        <div ref="messagesEnd"></div>
      </div>
      
      <!-- 语音播报弹窗 -->
      <VoicePlayer
        :show="isAppReady && showVoicePopup && voiceEnabled && isVoicePlaying"
        :is-paused="isPaused"
        :current-text="voicePlayingText"
        @toggle-pause="toggleVoicePause"
        @close="closeVoice"
      />
      
      <!-- 语音输入提示器 -->
      <VoiceInput
        :show="isAppReady && showVoiceInput && isListening"
      />
      
      <!-- 文件预览区域 -->
      <FileUpload
        :files="uploadedFiles"
        @remove="removeUploadedFile"
      />
      
      <!-- 输入区域 -->
      <div class="deepseek-input-container">
        <textarea
          v-model="currentMessage"
          class="deepseek-textarea"
          placeholder="输入您的问题，Ctrl + Enter 发送..."
          :disabled="isProcessing"
          @keydown="handleKeyDown"
        ></textarea>
        <div class="deepseek-input-actions">
          <!-- 语音输入按钮 -->
          <button class="deepseek-voice-input" @click="toggleVoiceInput" title="语音输入">
            <i class="bi" :class="isListening ? 'bi-mic-fill' : 'bi-mic'"></i>
          </button>
          <!-- 文件上传按钮 -->
          <label class="deepseek-file-upload" :class="{ 'disabled': isProcessing || isUploading }">
            <input type="file" @change="handleFileUpload" :disabled="isProcessing || isUploading" />
            <i class="bi bi-paperclip" v-if="!isUploading"></i>
            <span class="spinner-border spinner-border-sm" v-else></span>
          </label>
          <button 
            class="deepseek-send-button" 
            @click="sendMessage" 
            :disabled="isProcessing || (!currentMessage.trim() && uploadedFiles.length === 0)">
            <i class="bi bi-send"></i>
          </button>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, nextTick, watch, onUpdated } from 'vue'
import { marked } from 'marked'
import Prism from 'prismjs'
import { ElMessage, ElMessageBox } from 'element-plus'
import VoicePlayer from './components/voice/VoicePlayer.vue'
import VoiceInput from './components/voice/VoiceInput.vue'
import FileUpload from './components/file/FileUpload.vue'
import { useChatStore } from './stores/chat'
import { chatService } from './api/chat'

// 状态
const chatStore = useChatStore()
const messages = ref([])  // 初始化为空数组
const currentMessage = ref('')
const messagesEnd = ref(null)
const isProcessing = ref(false)
const isListening = ref(false)
const isVoicePlaying = ref(false)
const isPaused = ref(false)
const voiceEnabled = ref(false)
const avatarEnabled = ref(false)
const showVoicePopup = ref(false)
const showVoiceInput = ref(false)
const isAppReady = ref(false)
const isUploading = ref(false)
const uploadedFiles = ref([])
const voicePlayingText = ref('')

// 优化 marked 配置，增强 markdown 兼容性和代码高亮
marked.setOptions({
  breaks: true, // 支持换行
  gfm: true,    // 支持表格、任务列表等
  headerIds: false, // 避免标题id冲突
  highlight: function(code, lang) {
    if (Prism.languages[lang]) {
      return Prism.highlight(code, Prism.languages[lang], lang);
    }
    return code;
  }
})

// 监听 store 中的消息变化
watch(() => chatStore.messages, (newMessages) => {
  messages.value = newMessages || []
}, { immediate: true, deep: true })

// 方法
const scrollToBottom = async () => {
  if (messagesEnd.value) {
    messagesEnd.value.scrollIntoView({ behavior: 'smooth', block: 'end' })
  }
}

const createNewChat = () => {
  ElMessageBox.confirm(
    '确定要开始新的对话吗？当前对话将被清空。',
    '提示',
    {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning',
    }
  ).then(() => {
    chatStore.clearMessages()
    ElMessage.success('已开始新的对话')
  }).catch(() => {})
}

const handleKeyDown = (e) => {
  if (e.key === 'Enter' && e.ctrlKey) {
    e.preventDefault()
    sendMessage()
  }
}

const handleFileUpload = async (event) => {
  const file = event.target.files[0]
  if (!file) return
  isUploading.value = true
  try {
    const result = await chatService.uploadFile(file)
    uploadedFiles.value.push({
      id: result.fileId,
      name: result.fileName,
      size: result.fileSize,
      uploading: false
    })
  } catch (e) {
    ElMessage.error('文件上传失败')
  } finally {
    isUploading.value = false
  }
}

const sendMessage = async () => {
  if (!currentMessage.value.trim() && uploadedFiles.value.length === 0) return
  // 立即清空附件
  uploadedFiles.value = []
  const message = currentMessage.value
  currentMessage.value = ''
  const userMessage = {
    id: Date.now(),
    content: message,
    isUser: true,
    timestamp: new Date().toISOString()
  }
  chatStore.addMessage(userMessage)
  await scrollToBottom()
  try {
    isProcessing.value = true
    const thinkingMessage = {
      id: Date.now(),
      content: '<div class="thinking-indicator"><div class="spinner"></div><span>AI 正在思考中...</span></div>',
      isUser: false,
      timestamp: new Date().toISOString(),
      thinking: true
    }
    const aiMessage = {
      id: Date.now(),
      content: '',
      isUser: false,
      timestamp: new Date().toISOString(),
      typing: true
    }
    chatStore.addMessage(thinkingMessage)
    await scrollToBottom()
    const fileIds = uploadedFiles.value.map(f => f.id) // 这里已清空，实际传递的fileIds为空
    await chatService.sendMessage(message, fileIds, (content) => {
      if (!aiMessage.content) {
        const thinkingIndex = chatStore.messages.findIndex(msg => msg.id === thinkingMessage.id)
        if (thinkingIndex !== -1) {
          chatStore.messages.splice(thinkingIndex, 1, aiMessage)
        }
      }
      aiMessage.content += content
      const index = chatStore.messages.findIndex(msg => msg.id === aiMessage.id)
      if (index !== -1) {
        chatStore.messages.splice(index, 1, {
          ...chatStore.messages[index],
          content: marked(aiMessage.content),
          typing: true
        })
      }
    })
    const index = chatStore.messages.findIndex(msg => msg.id === aiMessage.id)
    if (index !== -1) {
      chatStore.messages.splice(index, 1, {
        ...chatStore.messages[index],
        typing: false
      })
    }
    if (voiceEnabled.value) {
      voicePlayingText.value = aiMessage.content
      isVoicePlaying.value = true
      showVoicePopup.value = true
    }
  } catch (error) {
    const thinkingIndex = chatStore.messages.findIndex(msg => msg.thinking)
    if (thinkingIndex !== -1) {
      chatStore.messages.splice(thinkingIndex, 1)
    }
    ElMessage.error('发送消息失败，请重试')
  } finally {
    isProcessing.value = false
    await scrollToBottom()
  }
}

const likeMessage = (message) => {
  message.liked = !message.liked
  if (message.liked) {
    message.disliked = false
  }
}

const dislikeMessage = (message) => {
  message.disliked = !message.disliked
  if (message.disliked) {
    message.liked = false
  }
}

const copyMessage = (message) => {
  navigator.clipboard.writeText(message.content)
  ElMessage.success('已复制到剪贴板')
}

const retryMessage = (message) => {
  // 实现重试逻辑
}

const expandMessage = (message) => {
  // 实现展开全文逻辑
}

const toggleVoiceInput = () => {
  isListening.value = !isListening.value
  showVoiceInput.value = isListening.value
}

const toggleVoicePause = () => {
  isPaused.value = !isPaused.value
}

const closeVoice = () => {
  isVoicePlaying.value = false
  showVoicePopup.value = false
  isPaused.value = false
}

const removeUploadedFile = (fileId) => {
  uploadedFiles.value = uploadedFiles.value.filter(f => f.id !== fileId)
}

// 代码块复制功能
function addCopyButtons() {
  nextTick(() => {
    document.querySelectorAll('.message-content pre').forEach(pre => {
      if (pre.querySelector('.copy-code-btn')) return; // 避免重复添加
      const btn = document.createElement('button');
      btn.className = 'copy-code-btn';
      btn.innerHTML = '<i class="bi bi-clipboard"></i>';
      btn.title = '复制代码';
      btn.onclick = function(e) {
        e.stopPropagation();
        const code = pre.querySelector('code');
        if (code) {
          navigator.clipboard.writeText(code.innerText).then(() => {
            ElMessage.success('代码已复制');
          });
        }
      };
      pre.style.position = 'relative';
      pre.appendChild(btn);
    });
  });
}

onMounted(() => {
  isAppReady.value = true
  scrollToBottom()
  addCopyButtons()
})

onUpdated(() => {
  addCopyButtons()
})
</script>

<style>
@import './styles/theme.css';
@import './styles/chat.css';
@import 'bootstrap/dist/css/bootstrap.min.css';
@import 'bootstrap-icons/font/bootstrap-icons.css';

[v-cloak] {
  display: none !important;
}

/* 添加打字机效果相关样式 */
.typing {
  white-space: pre-wrap;
  word-break: break-word;
}

.typed-cursor {
  color: var(--deepseek-primary);
  font-weight: bold;
}

/* 打字光标样式 */
.typing-cursor {
  display: inline-block;
  width: 2px;
  height: 1.2em;
  background-color: var(--deepseek-primary);
  margin-left: 2px;
  animation: blink 1s infinite;
  vertical-align: middle;
}

@keyframes blink {
  0%, 100% { opacity: 1; }
  50% { opacity: 0; }
}
</style>
